(function(root, factory) {
    if (typeof define == "function" && define.amd)
        define(["baseTrack", "jquery"], factory);
    else
        factory();
})(this, function(baseTrack) {
    this.legendofkage = this.legendofkage || {};
    baseTrack && (this.legendofkage.baseTrack = baseTrack);


    function OlTrack(map, opt) {
        var map_, vectorOverlay,
            personOverlay,
            trackData = {},
            historyTrackData = [],
            historyTrackPoints = [],
            intervalId, totalDistance = 0,
            lableDisText = '0公里',
            labelText = '',
            isHandleData = false;

        //轨迹状态
        var trackState = {
            playing: "playing",
            pause: "pause",
            stop: "stop",
            current: "stop"
        }

        //指明创建的marker类型
        var markerType = {
            personMarker: "personMarker",
            evtMarker: "evtMarker",
            numberFeature: "numberFeature"
        }

        var optSettings = {
            speed: 500, //播放速度
            calcDistance: false, //是否计算里程
            autoAdjustViewport: false, //轨迹播放超出边界时，是否自动调整视野(可见范围).
            baseUrl: "./images/", //人员或事件覆盖物相关图片根路径
            personMarker: {
                icon: {
                    size: [50, 45],
                    offset: [14, 0],
                },
                label: {
                    offset: [-20, -25],
                    style: {
                        backgroundColor: "#FFFFAD",
                        color: "#00000",
                        fontSize: 12,
                        fontName: "arial",
                        border: "border:none"
                    }
                }
            },
            evtFeature: {
                icon: {
                    url: 'evt.png'
                }
            }
        };
        if (opt.calcDistance && !opt.personMarker.label.offset) {
            optSettings.personMarker.label.offset = [-90, -25];
        }
        OlTrack.__super__ && OlTrack.__super__.constructor.apply(this, arguments);

        if (!map) {
            throw new Error("构造函数中未传入地图对象!");
        }
        map_ = map;
        opt = opt || {};
        if (!opt.dataSource) {
            throw new Error("配置对象未设置轨迹数据源!");
        }
        legendofkage.Util.extend(true, optSettings, opt);

        initOverlay();
        listenTrackProcess.call(this);

        /**
         * 创建Overlay，并返回
         * 
         * @param {any} point 覆盖物平面坐标
         * @param {any} type 覆盖物类型
         * @param {any} opt 配置对象
         * @returns 
         */
        function createOverlay(point, type, opt) {
            opt = opt || {};
            Object.assign(optSettings[type], opt);
            if (type == markerType.personMarker) {
                var img = optSettings.baseUrl + 'ol3/walk_back_0.png';
                var icon = new TyMapUtils.Icon(img, opt.icon.size, { offset: opt.icon.offset });
                var label = new TyMapUtils.Label(opt.label.text, {
                    offset: opt.label.offset,
                    style: opt.label.style
                });
                var marker = new TyMapUtils.Marker({
                    id: opt.id,
                    position: [point.x, point.y],
                    icon: icon,
                    label: label,
                    offset: [-(opt.icon.size[0] / 2), -(opt.icon.size[1] / 2)]
                });
                marker.setFlag({
                    id: opt.id,
                    name: opt.label.text
                });
                var overlay = marker.createOverlay();
                overlay.flag = marker.flag;
                overlay.setImage = marker.icon.setImage.bind({
                    domElement: marker.icon.domElement
                });
                overlay.setContent = marker.label.setContent.bind({
                    domElement: marker.label.domElement
                });
                return overlay;
            }
        }

        /**
         * 初始化矢量图层，该图层用来承载事件、分段轨迹序号、以及轨迹线等feature
         * 
         */
        function initOverlay() {
            vectorOverlay = new ol.layer.Vector({
                source: new ol.source.Vector(),
                map: map_,
                style: new ol.style.Style({
                    stroke: new ol.style.Stroke({
                        color: '#f00',
                        width: 1
                    }),
                    fill: new ol.style.Fill({
                        color: 'rgba(255,0,0,0.1)'
                    })
                })
            });
        }


        /**
         * 创建序号feature
         *
         * @param {any} point 平面坐标
         * @param {any} text  序号文本
         * @returns 
         */
        function createNumberFeature(point) {
            var text = this.getId().toString();
            var style = new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 8,
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 173,0.6)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: 'red',
                        width: 1
                    }),
                }),
                text: new ol.style.Text({
                    font: '12px Microsoft YaHei,Calibri,sans-serif',
                    fill: new ol.style.Fill({
                        color: '#000'
                    }),
                    text: text,
                    textAlign: 'center'
                })
            });
            var feature = new ol.Feature({
                geometry: new ol.geom.Point(point)
            });
            feature.setStyle(style);
            return feature;
        }

        /**
         * 创建事件feature
         * 
         * @param {any} point 平面坐标
         * @param {any} imgUrl 人员图标文件
         * @returns 
         */
        function createEvtFeature(point, imgUrl) {
            imgUrl = imgUrl || optSettings.baseUrl + optSettings.evtFeature.icon.url;
            var style = new ol.style.Style({
                image: new ol.style.Icon({
                    anchor: [0.5, 0.5],
                    src: imgUrl
                })
            });
            var feature = new ol.Feature({
                geometry: new ol.geom.Point(point)
            });
            feature.setStyle(style);
            return feature;
        }


        /**
         * 创建绘制轨迹线路时的feature
         * 
         * @param {any} point 投影后的平面坐标
         * @returns 
         */
        function createPolyLineFeature(point) {
            var style = new ol.style.Style({
                stroke: new ol.style.Stroke({
                    width: 2,
                    color: "rgba(255, 0, 0,1)"
                })
            });
            var feature = new ol.Feature({
                geometry: new ol.geom.LineString([point])
            });
            feature.setStyle(style);
            return feature;
        }



        /**
         * 以米字型结构，判断轨迹播放当中的人员行走方向
         * 
         * @param {any} trackObj 
         * @returns 
         */
        function adjustmentPersonOverlayDir(trackObj) {
            if (!trackObj.lastNode) {
                this.personOverlay.set('obWalk', {
                    direction: "ol3/walk_front_0",
                    type: 0
                });
                return;
            }
            var walkDir;
            var type = Math.abs(this.personOverlay.get('obWalk').type - 1);
            var deg = legendofkage.Util.map.ol.getRotation(trackObj.lastNode.point, trackObj.point);
            if (trackObj.point[0] == trackObj.lastNode.point[0]) {
                if (trackObj.point[1] > trackObj.lastNode.point[1]) {
                    walkDir = "ol3/walk_front_" + type;
                } else {
                    walkDir = "ol3/walk_back_" + type;
                }
            } else {
                if (deg > 0) {
                    if (deg <= 45) {
                        walkDir = "ol3/walk_right_" + type;
                    } else if (deg <= 135) {
                        walkDir = "ol3/walk_front_" + type;
                    } else {
                        walkDir = "ol3/walk_left_" + type;
                    }
                } else {
                    if (deg <= -180) {
                        walkDir = "ol3/walk_left_" + type;
                    } else if (deg <= -135) {
                        walkDir = "ol3/walk_back_" + type;
                    } else {
                        walkDir = "ol3/walk_right_" + type;
                    }
                }
            }

            this.personOverlay.set('obWalk', {
                direction: walkDir,
                type: type
            });
            this.personOverlay.setImage(optSettings.baseUrl + walkDir + '.png');
            this.personOverlay.setPosition(trackObj.point);
        }


        /**
         * 监听轨迹播放进度及状态
         * 
         */
        function listenTrackProcess() {
            var track = this;
            track.on('processing', function(target) {
                if (trackState.current == trackState.pause) {
                    clearTimeout(intervalId);
                }
            })
        }

        /**
         * 格式化轨迹数据(无论后台返回什么字段的数据，都要转化为统一要求的数据格式)
         * 
         * @param {any} type ListTP(格式化巡查员轨迹数据),ListTE(格式化事件数据)
         * @param {any} fn 
         * @returns 
         */
        function formatTrackData(type, fn) {
            isHandleData = true;
            return optSettings.dataSource[type].map(function(item, index) {
                var obj = {
                    point: null,
                    date: null,
                    dateString: '',
                    tag: item
                };
                var newObj = fn(obj, item);
                if (newObj != obj) {
                    throw new TypeError("dataAdapter方法中回调函数返回错误的数据类型!");
                }
                if (!newObj.point || !newObj.date) {
                    throw new Error("dataAdapter方法中回调函数的返回对象属性值有误,其point,date属性均必须有值!");
                }
                newObj.__data__ = item;
                newObj.__type__ = type;
                newObj.__time__ = newObj.date.getTime(); //排序用
                return newObj;
            })
        }

        /**
         * 循环绘制轨迹
         * 
         */
        function drawTrack() {
            var trackObj = trackData.allData.shift();
            if (trackObj) {
                if (trackObj.__type__ == "ListTP") {
                    adjustmentPersonOverlayDir.call(this, trackObj);
                    if (optSettings.calcDistance) {
                        if (trackObj.lastNode != null) {
                            var labelTxt = "";
                            var lineString = new ol.geom.LineString([trackObj.lastNode.point, trackObj.point]);
                            totalDistance += lineString.getLength();
                            if (totalDistance < 1000) {
                                labelTxt += this.personOverlay.flag.name + " " + trackObj.dateString + " " + totalDistance.toFixed(2) + "米";
                            } else {
                                labelTxt += this.personOverlay.flag.name + " " + trackObj.dateString + " " + (totalDistance / 1000).toFixed(2) + "公里";
                            }
                            this.personOverlay.setContent(labelTxt);
                        }
                    }
                    var polylineFeature = vectorOverlay.getSource().getFeatureById('polylineFeature');
                    if (!polylineFeature) {
                        polylineFeature = createPolyLineFeature(trackObj.point);
                        polylineFeature.setId('polylineFeature');
                        vectorOverlay.getSource().addFeature(polylineFeature);
                    } else {
                        polylineFeature.getGeometry().appendCoordinate(trackObj.point); //绘制路线；
                    }
                    historyTrackPoints.push(trackObj.point);
                    //如果轨迹点超出了范围，就自动调整!
                    if (optSettings.autoAdjustViewport) {
                        map_.getView().fit(polylineFeature.getGeometry());
                    }
                } else {
                    //对事件的处理
                    var evtFeature = createEvtFeature(trackObj.point);
                    evtFeature.flag = trackObj;
                    vectorOverlay.getSource().addFeature(evtFeature);
                    var self = this;
                    //单击事件只注册一次即可,所有的事件feature统一处理
                    if (!('selectInteraction' in vectorOverlay)) {
                        var selectClick = new ol.interaction.Select({
                            condition: ol.events.condition.click,
                            layers: [vectorOverlay]
                        });
                        var evtHandler = function(feature) {
                            var keys = Object.keys(this.evtType);
                            keys.forEach(function(item, index) {
                                if (item.indexOf(':') >= 0 && item.split(":")[1] == "click") {
                                    self.dispatch(item, {
                                        evtType: item.split(":")[1],
                                        target: feature.flag.__data__,
                                        markerType: markerType.evtMarker
                                    });
                                }
                            })
                        };
                        map_.addInteraction(selectClick);
                        selectClick.on('select', function(e) {
                            if (e.target.getFeatures().getLength() > 0) {
                                evtHandler.call(self, e.target.getFeatures().getArray()[0]);
                            }
                        });
                        vectorOverlay.selectInteraction = true;
                    }
                }
                intervalId = setTimeout(arguments.callee.bind(this), optSettings.speed);
                //将来对正在播放的轨迹往回拉时，可以用到这个数据
                historyTrackData.push(trackObj);
                this.dispatch('processing', {
                    total: trackData.listTP.length,
                    current: historyTrackPoints.length
                });
            } else {
                //正常情况下轨迹播放完毕，触发事件，以便通知播放器本身(播放器根据设置可能自动播放下一轨迹)
                trackState.current = trackState.stop;
                this.dispatch(trackState.stop, {
                    evtType: trackState.stop,
                    target: this
                })
            }
        }


        /**
         * 数据适配器
         * 
         * @param {any} fn 该回调函数有两个参数，第一个参数是要返回的目标对象，
         * 第二个参数是原始的轨迹点数据，注意point的属性格式为[],例如：
         * tracks.forEach(function(item) {
                item.dataAdapter(function(target, from) {
                    target.point = [from.BdX, from.BdY];
                    target.date = from.Date;
                    target.dateString = from.DateString;
                    return target;
                });
            })
         */
        this.dataAdapter = function(fn) {
            var lastNode = null;
            trackData.listTP = formatTrackData("ListTP", fn);
            trackData.listTP.sort(function(a, b) {
                return a.__time__ - b.__time__;
            });
            trackData.listTP.forEach(function(item, index) {
                if (index == 0) {
                    item.lastNode = null;
                    lastNode = item;
                } else {
                    item.lastNode = lastNode;
                    lastNode = item;
                }
            })
            trackData.listTE = formatTrackData("ListTE", fn);
            //人员轨迹跟案件合并，按时间排序，这样就解决了边播放巡查轨迹边陆续带出案件的功能
            trackData.allData = trackData.listTP.concat(trackData.listTE);
            trackData.allData.sort(function(a, b) {
                return a.__time__ - b.__time__;
            });
        }


        /**
         * 当前轨迹的状态
         * 
         * @returns 
         */
        this.getState = function() {
            return trackState.current;
        }


        /**
         * 设置播放速度
         * 
         * @param {any} speed 
         */
        this.setPlaySpeed = function(speed) {
            if (isNaN(speed))
                throw new Error("setPlaySpeed传进来的参数不是一个有效的速度值");
            optSettings.speed = speed
        }



        /**
         * 开始绘制轨迹
         * 
         */
        this.run = function() {
            if (!isHandleData) {
                throw new Error("未调用formatTrackData方法，格式化用户轨迹跟事件数据!");
            }
            if (trackData.allData.length > 0 && trackState.current != trackState.playing) {
                if (!this.personOverlay) {
                    this.personOverlay = createOverlay(trackData.allData[0].point, markerType.personMarker, optSettings.personMarker);
                    map_.addOverlay(this.personOverlay);
                    adjustmentPersonOverlayDir.call(this, trackData.allData[0]);
                }
                var numberFeature = vectorOverlay.getSource().getFeatureById('numberFeature');
                if (!numberFeature) {
                    numberFeature = createNumberFeature.call(this, trackData.allData[0].point);
                    numberFeature.setId('numberFeature');
                    vectorOverlay.getSource().addFeature(numberFeature);
                }
                trackState.current = trackState.playing;
                drawTrack.call(this);
            }
        }


        /**
         * 暂停绘制轨迹
         * 
         */
        this.pause = function() {
            if (trackState.current == trackState.playing) {
                trackState.current = trackState.pause;
            }
        }


        /**
         * 停止绘制轨迹
         * 
         */
        this.stop = function() {
            if (trackState.current == trackState.playing || trackState.current == trackState.pause) {
                trackState.current = trackState.stop;
                this.dispose();
            }
        }


        /**
         * 清除资源,当播放器调用stop方法时，则调用该方法
         * 
         */
        this.dispose = function() {
            clearTimeout(intervalId);
            this.unAll();
            var vecSource = vectorOverlay.getSource();
            vecSource.clear();
            map_.removeLayer(vectorOverlay);
            this.personOverlay && map_.removeOverlay(this.personOverlay);
            this.personOverlay = null;
            trackData.listTP && (trackData.listTP.length = 0);
            trackData.listTE && (trackData.listTE.length = 0);
            trackData.allData && (trackData.allData.length = 0);
        }

        this.clearPersonMarker = function() {
            if (this.personOverlay) {
                this.personOverlay && map_.removeOverlay(this.personOverlay);
            }
            this.personOverlay = null;
        }

    }


    legendofkage.Util.inherits(OlTrack, legendofkage.BaseTrack);

    /**
     * 
     * 注册marker事件(主要是针对事件数据)
     * @param {any} type 
     * @param {any} callbackFn 
     */
    OlTrack.prototype.addEventListener = function(type, callbackFn) {
        if (type && typeof type == "string" && typeof callbackFn == "function")
            this.on("marker:" + type, callbackFn);
    }

    legendofkage.OlTrack = OlTrack;
    return legendofkage.OlTrack;
});